﻿#region AppServices License

// Product: 
// AppServices
// http://appservices.codeplex.com
//
// Author:
// Pawel Idzikowski
// http://www.polenter.com
// mailto:idzikowski@polenter.com?subject=AppServices-Question
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the author(s) be held liable for any damages arising from
// the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//    1. The origin of this software must not be misrepresented; you must not
//      claim that you wrote the original software. If you use this software
//      in a product, an acknowledgment in the product documentation would be
//      appreciated but is not required.
//
//    2. Altered source versions must be plainly marked as such, and must not
//      be misrepresented as being the original software.
//
//    3. This notice may not be removed or altered from any source distribution.

#endregion

using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Polenter.Services.Advanced
{
    /// <summary>
    /// Summary description for ServiceInfoComparerTests
    /// </summary>
    [TestClass]
    public class ServiceInfoComparerTests
    {
        public ServiceInfoComparerTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void ServiceBNeedsA()
        {
            AppServices services = new AppServices();

            services.AddService<IServiceA>(new ServiceA());
            services.AddService(new ServiceBNeedsIA());

            var list = new List<ServiceInfo>(services.GetServices());
            list.Sort(new ServiceInfoComparer());

            Assert.AreEqual(typeof(IServiceA), list[0].ServiceType);
            Assert.AreEqual(typeof(ServiceBNeedsIA), list[1].ServiceType);
        }

        [TestMethod]
        public void ServiceANeedsB()
        {
            AppServices services = new AppServices();

            services.AddService(new ServiceANeedsIB());
            services.AddService<IServiceB>(new ServiceB());

            var list = new List<ServiceInfo>(services.GetServices());
            list.Sort(new ServiceInfoComparer());

            Assert.AreEqual(typeof(IServiceB), list[0].ServiceType);
            Assert.AreEqual(typeof(ServiceANeedsIB), list[1].ServiceType);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ServiceANeedsBAndViceVersa()
        {
            AppServices services = new AppServices();

            services.AddService(new ServiceANeedsBWhichNeedsIA());
            services.AddService(new ServiceBNeedsAWhichNeedsIB());

            var list = new List<ServiceInfo>(services.GetServices());
            list.Sort(new ServiceInfoComparer());
        }

        public interface IServiceA
        {

        }

        public interface IServiceB
        {

        }

        public class ServiceA : IServiceA
        {
            
        }

        public class ServiceB : IServiceB
        {

        }

        public class ServiceANeedsIB
        {
            [Service]
            public IServiceB ServiceB { get; set; }
        }

        public class ServiceBNeedsIA
        {
            [Service]
            public IServiceA ServiceA { get; set; }
        }

        public class ServiceANeedsBWhichNeedsIA
        {
            [Service]
            public ServiceBNeedsAWhichNeedsIB ServiceB { get; set; }
        }

        public class ServiceBNeedsAWhichNeedsIB
        {
            [Service]
            public ServiceANeedsBWhichNeedsIA ServiceA { get; set; }
        }
    }
}
